/**
 * 面向管理后端的系统功能接口
 */
import db, { mysql } from 'src-ssr/db/connect';
import TableHelper from 'src-ssr/db/tableHelper';
import * as tools from 'src-ssr/util/common';
import autocode from 'src-ssr/util/autocode';
import shortid from 'shortid';
import md5 from 'md5';
import logs from 'src-ssr/util/logs';
import workflow from 'src-ssr/util/workflow';
import schedule from 'src-ssr/util/schedule';
import { Sequelize, Op, QueryTypes } from 'sequelize';
import models, { sequelize } from 'src-ssr/db/sequelize';
import mDict from 'src-ssr/util/dictionary';

/**
 * 修改密码
 * @param {string} req.body.pwd 新密码
 */
export const changePwd = async (req, res) => {
  const { pwd } = req.body;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  await models.m_users.update({
    password: Sequelize.fn('MD5', Sequelize.literal(`CONCAT(${mysql.escape(pwd)}, salt)`))
  }, { where: { id: user.id } });

  res.json({ result: 'ok' });
}

// 获取网站配置
export const getSiteConfig = async (req, res) => {
  const site = await tools.getSystemConfig('site', 0); // 网站信息

  res.json({ site });
}

// 获取菜单及字典
export const getGeneralConfig = async (req, res) => {
  const { type } = req.query;
  const menuName = type === 'm' ? 'menu_manager' : 'menu_tenant';

  const menu = await tools.getSystemConfig(menuName, 0); // 菜单信息
  const dictionary = await mDict.getHybridDict(0); // 数据字典

  // 把菜单里的隐藏项剔除
  menu.menu = menu.menu.filter(v => !v.hidden);
  // 把菜单里的隐藏权限给剔除
  for (const row of menu.menu) {
    for (const key in row.right) {
      if (row.right[key] === 'hidden') {
        delete row.right[key];
      }
    }
  }
  // 递归建树
  function buildTree (data, parent) {
    const tree = [];
    data.forEach(node => {
      if (node.parent == parent) {
        const children = buildTree(data, node.name);
        if (children.length) {
          node.children = children;
        }
        tree.push(node);
      }
    });
    return tree;
  }
  menu.tree = buildTree(menu.menu, null);

  // 使用深度优先遍历树，将树形结构转换为数组
  function treeToArray (tree) {
    const result = [];
    function dfs (node) {
      result.push(node);
      if (node.children) {
        node.children.forEach(child => dfs(child));
      }
    }
    tree.forEach(node => dfs(node));
    return result;
  }
  menu.menu = treeToArray(menu.tree);

  res.json({ menu, dictionary });
}

// 获取数据字典
// @param {array, string} req.body.type 字典类型，可以为数组，也可以是字符串
export const getDataDict = async (req, res) => {
  const { types } = req.body;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  const dict = await mDict.getDynamicDict(types, user.tid);

  res.json(dict);
}

// 获取配置参数
export const getConfig = async (req, res) => {
  const { key } = req.query;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  if (key) {
    const fields = await tools.getSystemConfig(key, user.tid);
    res.json(fields);
  } else {
    res.json({ result: 'fail' });
  }
}

// 获取权限
export const userRights = async (req, res) => {
  const { module, right } = req.body;
  const rights = await tools.getUserRights(req.get('Authorization').split(' ')[1], module, right);
  res.send(rights);
}

// 通知人
export const noticeUser = async (req, res) => {
  const { title, message, module, uid } = req.body;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  if (uid) {
    workflow.sendCommand(uid, {
      message,
      module
    }, title || '通知', user.id, {
      id: 'notice',
      data: {
        first: message,
        keyword1: '',
        keyword2: '',
        keyword3: '当前用户',
        remark: `发起人：${user.nickname}`
      }
    }, user.id);
  }
  res.json({ result: 'ok' });
}

// 取消息
export const getUserMessage = async (req, res) => {
  const page = req.body.page || 1;
  const size = req.body.size || 30;

  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  // 取消息
  const [rows] = await mysql.query(`SELECT m.id, m.create_time, FROM_UNIXTIME(m.create_time, '%Y/%m/%d %H:%i') createtime,
    m.title, m.message, m.module, IF(IFNULL(read_time, '')='', 1, 0) is_new, u.nickname from_user
    FROM t_message_logs m
    LEFT JOIN m_users u ON m.sender=u.id
    WHERE m.msg_type='user' AND JSON_CONTAINS(m.receiver, '${mysql.escape(user.id)}') AND m.tenant_id=${user.tid}
    ORDER BY m.id DESC
    LIMIT ${(page - 1) * size}, ${size}`);

  // 置消息已读
  const idArray = rows.filter(v => v.is_new).map(v => v.id);
  if (idArray.length > 0) {
    models.message_logs.update({ read_time: Math.floor(Date.now() / 1000) }, { where: { id: idArray } });
  }

  res.json(rows);
}

// 取新消息数量
export const getNewMessageCount = async (req, res) => {
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  const [rows] = await mysql.query(`SELECT COUNT(*) cnt
    FROM t_message_logs
    WHERE msg_type='user' AND IFNULL(read_time, '')='' AND JSON_CONTAINS(receiver, '${mysql.escape(user.id)}') AND tenant_id=${user.tid}`)
  res.json({
    newMessage: rows[0].cnt
  });
}

// 删除图片
export const unlinkImage = (req, res) => {
  const { images } = req.body;
  tools.deleteImage(images);
  res.send('ok');
}

// 删除上传文件
export const unlinkFiles = (req, res) => {
  const { files } = req.body;
  tools.deleteFiles(files);
  res.send('ok');
}

/**
 * 自动编号
 * @param {string} code 编码 对应autocode表的code字段
 * @param {string} custom 自定义内容
 * */
export const getAutoCode = async (req, res) => {
  const { code, custom, digits } = req.body;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);
  const { tid } = user;

  res.send(await autocode.newCode({ tid, code, user, custom, digits }));
}

/**
 * 检查编号重复
 * @param {string} req.module 模块名称
 * @param {array} req.values 待查重的数据 {field1: value1, field2: value2,...}
 * @param {array} req.exclude 排除在外的数据 [field, value]
 * */
export const checkRepeatCode = async (req, res) => {
  const { code, values, exclude } = req.body;
  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);
  const { tid } = user;

  res.send(await autocode.checkRepeat(tid, code, values, exclude));
}

/**
 * 获取地区树
 */
export const getRegions = async (req, res) => {
  const regions = await tools.regionTree();
  res.json(regions);
};

/* 提取用户信息 */
export const getUserInfo = async (req, res) => {
  const login = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);

  // 取租户信息
  const tenantInfo = await models.m_tenants.findOne({
    attributes: ['id', 'tenant_name', 'state', 'company'],
    where: { id: login.tid },
    raw: true
  });

  // 取用户信息
  const userInfo = await models.m_users.findOne({
    attributes: ['id', 'nickname', 'rights', 'headimg', 'state'],
    include: [{
      model: models.m_roles,
      attributes: ['id', 'role_name']
    }],
    where: {
      id: login.id
    },
    raw: true
  });

  // 后端用户取是否为超级管理员
  if (login.tid === 0) {
    const config = await tools.getSystemConfig('menu_manager', login.tid);
    const superId = config.super.id;
    if (superId.indexOf(login.id) >= 0) {
      userInfo.rights._super_ = true;
    }
  }

  res.json({
    tenant: tenantInfo,
    user: {
      id: userInfo.id,
      nickname: userInfo.nickname,
      rights: userInfo.rights,
      headimg: userInfo.headimg,
      state: userInfo.state
    },
    role: {
      id: userInfo['m_role.id'],
      role_name: userInfo['m_role.role_name']
    }
  });
}

// 取全局域名
export const webDomain = async (req, res) => {
  res.json({ domain: await tools.globalHost() });
};

/**
 * 取自定义参数配置
 * @param {string} key 配置名称
 * @param {boolean} pub 是否公共，非必需项 若有值，则取公共配置，否则取私有配置
 */
export const getStorage = async (req, res) => {
  const { key, pub } = req.query;

  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);
  const config = await models.m_storage.findOne({
    attributes: ['value'],
    where: {
      key,
      tenant_id: user.tid,
      user_id: pub === 'true' ? 0 : user.id
    },
    raw: true
  });

  res.json(config && config.value[key]);
};

/**
 * 设置自定义参数配置
 * @param {string} key 配置名称
 * @param {string} value 配置值
 * @param {boolean} pub 是否公共，非必需项 若有值，则设置公共配置，否则设置私有配置
 */
export const setStorage = async (req, res) => {
  const { key, value, pub } = req.body;
  const storageValue = typeof value === 'string' ? { _string: value } : value;

  const user = await tools.getLoginUser(req.get('Authorization').split(' ')[1]);
  const config = await models.m_storage.findOne({
    attributes: ['value'],
    where: {
      key,
      tenant_id: user.tid,
      user_id: (pub === true || pub === 'true') ? 0 : user.id
    },
    raw: true
  });

  let storage = {};
  if (config) {
    storage = config.value;
    storage[key] = value;

    await models.m_storage.update({ value: storage }, {
      where: {
        key,
        tenant_id: user.tid,
        user_id: (pub === true || pub === 'true') ? 0 : user.id
      }
    });
  } else {
    storage[key] = value;

    await models.m_storage.create({
      key,
      value: storage,
      tenant_id: user.tid,
      user_id: (pub === true || pub === 'true') ? 0 : user.id
    });
  }

  res.json({ result: 'ok' });
};
